/*
 * raveduino.ino
 *
 * This sketch controls the brightness of an LED based on the volume of an audio
 * signal sampled at an analog input.
 */

//#include "Arduino.h"

// Comment this line out if you are using a common-cathode LED
#define COMMON_ANODE_LED

#define AUDIO_PIN   A1
#define LED_PIN     9
#define RED_PIN     11
#define GREEN_PIN   3
#define BLUE_PIN    9

#define NUM_SAMPLES 100
#define MAX_AMP     500


void SetLEDColor(int red, int green, int blue);
void ColorMap1(int color);


int samples[NUM_SAMPLES];


void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  analogWrite(LED_PIN, 255);
}


void loop()
{
  int i;
  int avg, amp;
  int duty;
  int dur;
  int start = millis();

  // Get samples
  for (i=0; i<NUM_SAMPLES; i++) {
    samples[i] = analogRead(AUDIO_PIN);
  }
  dur = millis() - start;

  // Calculate the amplitude
  avg = 0;
  amp = 0;
  for (i=0; i<NUM_SAMPLES; i++) {
    avg += samples[i];
    if (samples[i] > amp) {
      amp = samples[i];
    }
  }
  avg /= NUM_SAMPLES;

  // Calculate the duty cycle
//  duty = constrain(map(amp, 0, MAX_AMP, 0, 255), 0, 255);
  duty = constrain(map(amp, 0, MAX_AMP, 0, 2039), 0, 2039);
  ColorMap1(duty);
//  analogWrite(RED_PIN,    255-duty);
//  analogWrite(GREEN_PIN,  255-duty);
//  analogWrite(BLUE_PIN,   255-duty);

  if (avg > MAX_AMP) {
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }

/*
  // Output to terminal
  Serial.print(amp);
  Serial.print("\t");
  Serial.print(avg);
  Serial.print("\t");
  Serial.println(dur);
*/

  delay(100);
}


// This function takes conventional RGB values and sets the LED color 
// accordingly, inverting the values if necessary for a common-anode RGB LED.
void SetLEDColor(int red, int green, int blue)
{
  constrain(red,   0, 255);
  constrain(green, 0, 255);
  constrain(blue,  0, 255);

#ifdef COMMON_ANODE_LED
    red   = 255 - red;
    green = 255 - green;
    blue  = 255 - blue;
#endif

  analogWrite(RED_PIN,   red);
  analogWrite(GREEN_PIN, green);
  analogWrite(BLUE_PIN,  blue);

  Serial.print(red);
  Serial.print("\t");
  Serial.print(green);
  Serial.print("\t");
  Serial.println(blue);
}

// This function takes a single number (0-2039) and maps it to RGB color values.
void ColorMap1(int color)
{
  int red, green, blue;

  color %= 2040;

  if (color < 256) {
    // transition to red
    red   = color;
    green = 0;
    blue  = 0;
  } else if (color < 511) {
    // transition to yellow
    red   = 255;
    green = map(color, 256, 510, 1, 255);
    blue  = 0;
  } else if (color < 766) {
    // transition to green
    red   = map(color, 511, 765, 254, 0);
    green = 255;
    blue  = 0;
  } else if (color < 1021) {
    // transition to aqua
    red   = 0;
    green = 255;
    blue  = map(color, 766, 1020, 1, 255);
  } else if (color < 1276) {
    // transition to white
    red   = map(color, 1021, 1275, 1, 255);
    green = 255;
    blue  = 255;
  } else if (color < 1531) {
    // transition to violet
    red   = 255;
    green = map(color, 1276, 1530, 254, 0);
    blue  = 255;
  } else if (color < 1786) {
    // transition to blue
    red   = map(color, 1531, 1785, 254, 0);
    green = 0;
    blue  = 255;
  } else { //color < 2040
    // transition to black (all off)
    red   = 0;
    green = 0;
    blue  = map(color, 1786, 2039, 254, 1);
  }

  SetLEDColor(red, green, blue);
  Serial.println(color);
}

